package cn.shiro.realm;


import cn.shiro.domain.Employee;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.Arrays;
import java.util.List;

public class EmployeeRealm extends AuthorizingRealm {
    //提供认证信息(EM)
    //参数的token是subject进行登录匹配传入的token：UsernameAndPasswordToken
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {

        //1:获取用户名
        //页面传入的账号
        //方式1:
/*        UsernamePasswordToken utoken = (UsernamePasswordToken) token;
        String username = utoken.getUsername();*/
        //方式2：
        String name = (String) token.getPrincipal();


        //2.以用户名作为条件，查询mysql数据库，得到用户对象（用户名/密码）
        //当前没有加入mybatis相关环境，假装在查询
        //Employee emp = employeeService.findByUsername(username)
        //暂且使用假数据来模拟数据库中真实的账号和密码
        Employee employee = null;
        employee = new Employee();
        employee.setUsername("admin");
        employee.setPassword("1");


        //3.将用户对象封装成认证info对象返回
        //(此时存在两种可能):
        //1>用户对象为null
        if (employee == null) {
            return null;
        }
        //2>用户对象不为null


        //获取token中需要登录的账号名
        Object username = token.getPrincipal();
        //如果账号存在，则返回一个 AuthenticationInfo 对象
        if(username.equals(employee.getUsername())){
            return new SimpleAuthenticationInfo(
                    employee,//身份对象，与主体subject绑定在一起的对象,暂时无用但后续要用（从数据库查询出来的需要进行密码匹配的用户对象）
                    employee.getPassword(),//该账号真正的密码，传给shiro做密码校验的
                    this.getName()//当前 Realm 的名称,暂时无用，不需纠结（也可以super，可自定义）
            );
        }
        return null;
    }

    //提供授权信息
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //1:获取当前登录用户对象的id/name
        //这个principals是什么东西呢，它意思是主要的角色，也就是当前登录对象本身，相当于当初SimpleAuthenticationInfo传过来的第一个参数
        //方式1:
        Employee employee = (Employee)principals.getPrimaryPrincipal();
        //方式2:
        //Object principal = SecurityUtils.getSubject().getPrincipal();//这个方法也是可以的，强转一下的话还是当前登录对象

        // 2:根据登录用户的id查询mysql数据，查询到其拥有的所有角色的编码(拥有角色/权限)
        //假装查询数据:
        //roleService.queryByEmpId(employee.getId())
        //permissionService.queryByEmpId(employee.getId())
        List<String> roleSns = Arrays.asList("hr","manager","seller");
        // 根据登录用户的 id 查询到其拥有的所有权限表达式
        List<String> expressions = Arrays.asList("employee:list","employee:save");

        // 3:将角色与权限封装到授权info对象中（将用户拥有的角色添加到授权信息对象中，供 Shiro 权限校验时使用）
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles(roleSns);
        // 将用户拥有的权限添加到授权信息对象中，供 Shiro 权限校验时使用
        info.addStringPermissions(expressions);
        return info;
    }
}